#ifndef _FS_H_
#define _FS_H_

#include <sys/types.h>

#define READ 0
#define WRITE 1

void buffer_init(long buffer_end);

#define MAJOR(a) (((unsigned)(a)) >> 8)
#define MINOR(a) ((a) & 0xff)

#define NAME_LEN 14
#define ROOT_INO 1

#define I_MAP_SLOTS 8
#define Z_MAP_SLOTS 8
#define SUPER_MAGIC 0x137F

#define NR_OPEN 20
#define NR_INODE 32
#define NR_FILE 64
#define NR_SUPER 8
#define NR_HASH 307
#define NR_BUFFERS nr_buffers
#define BLOCK_SIZE 1024

#define INODES_PER_BLOCK ((BLOCK_SIZE) / (sizeof(struct d_inode)))
#define DIR_ENTRIES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct dir_entry)))

struct buffer_head {
    char *b_data;               // 指向数据块（1KB）的指针
    unsigned long b_blocknr;    // 逻辑块号
    unsigned short b_dev;       // 设备号，0-空闲
    unsigned char b_uptodate;   // 是否更新
    unsigned char b_dirt;       // 脏位，0-未修改，1-修改过
    unsigned char b_count;      // 使用此结构的用户数
    unsigned char b_lock;       // 0 - 未上锁，1 - 上锁
    struct task_struct *b_wait; // 指向该缓冲区解锁的任务
    struct buffer_head *b_prev; // hash队列的上一块
    struct buffer_head *b_next; // hash队列的下一块
    struct buffer_head *b_prev_free;    // 空闲表上一块
    struct buffer_head *b_next_free;    // 空闲表下一块
};

struct d_inode {
    unsigned short i_mode;      // 文件的类型和属性(rwx)
    unsigned short i_uid;       // 文件所有者的用户id
    unsigned long i_size;       // 文件长度（字节）
    unsigned long i_time;       // 修改时间（从1970.1.1:0时算起，单位：秒）
    unsigned char i_gid;        // 文件所有者的组id
    unsigned char i_nlinks;     // 链接数
    unsigned short i_zone[9];   // 文件占用的逻辑块的块号
                                // zone[0]-zone[6]是直接块号
                                // zone[7]是一次间接块号
                                // zone[8]是二次间接块号
};

struct m_inode {
    unsigned short i_mode;      // 文件的类型和属性(rwx)
    unsigned short i_uid;       // 文件所有者的用户id
    unsigned long i_size;       // 文件长度（字节）
    unsigned long i_mtime;      // 修改时间（从1970.1.1:0时算起，单位：秒）
    unsigned char i_gid;        // 文件所有者的组id
    unsigned char i_nlinks;     // 链接数
    unsigned short i_zone[9];   // 文件占用的逻辑块的块号
                                // zone[0]-zone[6]是直接块号
                                // zone[7]是一次间接块号
                                // zone[8]是二次间接块号
/* these are in memory also */
    struct task_struct * i_wait;
    unsigned long i_atime;
    unsigned long i_ctime;
    unsigned short i_dev;   // i 节点号
    unsigned short i_num;   // 设备号
    unsigned short i_count;
    unsigned char i_lock;
    unsigned char i_dirt;
    unsigned char i_pipe;
    unsigned char i_mount;
    unsigned char i_seek;
    unsigned char i_update;
};

struct file {
    unsigned short f_mode;
    unsigned short f_flags;
    unsigned short f_count;
    struct m_inode *f_inode;
    off_t f_pos;
};

struct super_block {
    unsigned short s_ninodes;
    unsigned short s_nzones;
    unsigned short s_imap_blocks;
    unsigned short s_zmap_blocks;
    unsigned short s_firstdatazone;
    unsigned short s_log_zone_size;
    unsigned long s_max_size;
    unsigned short s_magic;
/* These are only in memory */
    unsigned short reserved;
    struct buffer_head * s_imap[8];
    struct buffer_head * s_zmap[8];
    unsigned short s_dev;
    struct m_inode * s_isup;
    struct m_inode * s_imount;
    unsigned long s_time;
    struct task_struct * s_wait;
    unsigned char s_lock;
    unsigned char s_rd_only;
    unsigned char s_dirt;
};

struct d_super_block {
    unsigned short s_ninodes;       // i节点数
    unsigned short s_nzones;        // 逻辑块数
    unsigned short s_imap_blocks;   // i节点位图所占块数
    unsigned short s_zmap_blocks;   // 逻辑块位图所占块数
    unsigned short s_firstdatazone; // 数据区第一个逻辑块的块号
    unsigned short s_log_zone_size; // log2(数据块数/逻辑块)
    unsigned long s_max_size;       // 最大文件长度
    unsigned short s_magic;         // 文件系统魔数
};

struct dir_entry {
    unsigned short inode;
    char name[NAME_LEN];
};

extern struct file file_table[NR_FILE];
extern struct super_block super_block[NR_SUPER];
extern struct buffer_head * start_buffer;
extern int nr_buffers;

extern void check_disk_change(int dev);
extern int floppy_change(unsigned int nr);
extern int ticks_to_floppy_on(unsigned int dev);
extern void floppy_on(unsigned int dev);
extern void floppy_off(unsigned int dev);
extern struct m_inode *namei(const char *pathname);
extern int open_namei(const char *pathname);
extern struct m_inode *iget(int dev, int nr);
extern struct m_inode *get_empty_inode(void);
extern struct buffer_head *getblk(int dev, int block);
extern void ll_rw_block(int rw, struct buffer_head *bh);
extern void brelse(struct buffer_head *buf);
extern struct buffer_head *bread(int dev, int block);
extern struct super_block *get_super(int dev);
extern int ROOT_DEV;

extern void mount_root(void);

#endif
